package session

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"gitee.com/xchengli/blog-lib/components"
	"gitee.com/xchengli/blog-lib/config"
	"gitee.com/xchengli/blog-lib/database"
	"gitee.com/xchengli/blog-lib/defines"
	"gitee.com/xchengli/blog-lib/zlog"
)

/*
*
Session
*/
type GuestSession defines.AdminUserLogin

// init
func (gs *GuestSession) Init(r *http.Request) *GuestSession {

	//启动Redis建立连接
	database.InitRedis()

	guestId, err := r.Cookie("guestId")
	if err != nil || guestId == nil {
		//随机生成
		gs.Key = components.Md5(time.Now().Format("2006-01-02 15:04:05") + "|" + components.GetRandomString(8))
	} else {
		gs.Key = guestId.Value
		err = gs.GetSession()
		if err != nil {
			ctx := components.NewContext()
			zlog.Error(ctx, err)
			return new(GuestSession)
		}

	}

	if gs.Key == "" {
		gs.Key = components.Md5(time.Now().Format("2006-01-02 15:04:05") + "|" + components.GetRandomString(8))
	}

	//设置过期时间
	gs.UpdateCacheTime()

	return gs
}

// 获取访客ID
func (gs *GuestSession) GetGuestId() string {
	return gs.Key
}

// SetSession
func (gs *GuestSession) SetSession() (err error) {
	guestId := gs.Key
	if guestId == "" {
		err = errors.New("guestId is empty")
		return
	}

	ctx := context.Background()

	// 将结构体转换为map
	sessionMap := map[string]interface{}{
		"Key":           gs.Key,
		"UID":           gs.UID,
		"Name":          gs.Name,
		"NiceName":      gs.NiceName,
		"Email":         gs.Email,
		"Phone":         gs.Phone,
		"FaceImg":       gs.FaceImg,
		"Status":        gs.Status,
		"Description":   gs.Description,
		"LastLoginIP":   gs.LastLoginIP,
		"LastLoginTime": gs.LastLoginTime,
		"LoginFrom":     gs.LoginFrom,
		"UserAgent":     gs.UserAgent,
	}

	err = database.RedisConn.HMSet(ctx, "ses."+guestId, sessionMap).Err()
	if err != nil {
		fmt.Println(err)
	}

	//设置过期时间
	gs.UpdateCacheTime()

	return
}

// GetSession
func (gs *GuestSession) GetSession() (err error) {
	guestId := gs.Key
	if guestId == "" {
		err = errors.New("guestId is empty")
		return
	}

	ctx := context.Background()

	// 获取所有字段
	result, err := database.RedisConn.HGetAll(ctx, "ses."+guestId).Result()
	if err != nil {
		return err
	}

	// 手动映射字段
	if uid, ok := result["UID"]; ok && uid != "" {
		fmt.Sscanf(uid, "%d", &gs.UID)
	}
	if name, ok := result["Name"]; ok {
		gs.Name = name
	}
	if niceName, ok := result["NiceName"]; ok {
		gs.NiceName = niceName
	}
	if email, ok := result["Email"]; ok {
		gs.Email = email
	}
	if phone, ok := result["Phone"]; ok {
		gs.Phone = phone
	}
	if faceImg, ok := result["FaceImg"]; ok {
		gs.FaceImg = faceImg
	}
	if status, ok := result["Status"]; ok && status != "" {
		fmt.Sscanf(status, "%d", &gs.Status)
	}
	if description, ok := result["Description"]; ok {
		gs.Description = description
	}
	if lastLoginIP, ok := result["LastLoginIP"]; ok {
		gs.LastLoginIP = lastLoginIP
	}
	if lastLoginTime, ok := result["LastLoginTime"]; ok {
		gs.LastLoginTime = lastLoginTime
	}
	if loginFrom, ok := result["LoginFrom"]; ok {
		if loginFromUint, err := strconv.ParseUint(loginFrom, 10, 8); err == nil {
			gs.LoginFrom = uint8(loginFromUint)
		}
	}
	if userAgent, ok := result["UserAgent"]; ok {
		gs.UserAgent = userAgent
	}

	//从数据库获取用户信息
	if gs.UID <= 0 {
		// TODO: 实现从数据库获取登录信息的逻辑
		// 这里需要根据实际的数据访问层来实现
		// loginService := &data.AdminLoginDataService{}
		// loginInfo, err := loginService.GetLoginWithUser(guestId)
		// if err != nil {
		// 	return err
		// }

		// //写入Session
		// gs.UID = loginInfo.UID
		// gs.Name = loginInfo.Name
		// gs.NiceName = loginInfo.NiceName
		// gs.Email = loginInfo.Email
		// gs.Phone = loginInfo.Phone
		// gs.FaceImg = loginInfo.FaceImg
		// gs.Status = loginInfo.Status
		// gs.Description = loginInfo.Description
		// gs.LastLoginIP = loginInfo.LastLoginIP
		// gs.LastLoginTime = loginInfo.LastLoginTime
		// gs.LoginFrom = loginInfo.LoginFrom
		// gs.UserAgent = loginInfo.UserAgent

		// err = gs.SetSession()
		// if err != nil {
		// 	return err
		// }
	}

	//设置过期时间
	gs.UpdateCacheTime()
	return
}

// 检查是否登陆
func (gs *GuestSession) CheckIsLogin() bool {
	if gs.UID <= 0 {
		return false
	}

	return true
}

// 更新缓存时间
func (gs *GuestSession) UpdateCacheTime() (err error) {
	guestId := gs.Key
	if guestId == "" {
		err = errors.New("guestId is empty")
		return
	}

	ctx := context.Background()
	err = database.RedisConn.Expire(ctx, "ses."+guestId, time.Duration(config.RunCFG.SessionTime)*time.Second).Err()
	return
}

// 清除Session
func (gs *GuestSession) Delete() (err error) {
	guestId := gs.Key
	if guestId == "" {
		err = errors.New("guestId is empty")
		return
	}

	ctx := context.Background()

	//清除Session
	err = database.RedisConn.Del(ctx, "ses."+guestId).Err()
	//重置数据
	gs = new(GuestSession)

	return
}
